1 Exemple guiat 1.1

1.1 Mètodes d’agregació k-means amb dades autogenerades


En aquest exemple generarem un conjunt de mostres aleatòries per a posteriorment fer servir l’algoritme k-means per agrupar-les. Es crearan les mostres al voltant de dos punts concrets. Així doncs, lo lògic serà agrupar en dos clústers. Donat que inicialment, en un problema real, no es coneix quin es el número idoni de clústers k, provarem primer amb dos (el valor òptim) i posteriorment amb 4 i 8 clústers. Per a avaluar la qualitat de cada procés d’agrupació farem servir la silueta mitjana. La silueta de cada mostra avalua com de bé o malament està classificada cada mostra en el clúster al que ha estat assignada. Per això es fa servir una fórmula que té en compte la distància a les mostres del seu clúster i la distància a les mostres del clúster veí més proper.

A l’hora de provar el codi que es mostra, és important tenir en compte que les mostres es generen de forma aleatòria i també que l’algoritme k-means té una inicialització aleatòria. Així doncs, en cada execució, s’obtindran uns resultats lleugerament diferents.

Lo primer que fem es carregar la llibreria clúster que conté les funcions que es necessiten

if (!require('cluster')) install.packages('cluster')
library(cluster)

Generem les mostres de forma aleatòria prenent com a centre els punts [0,0] i [5,5].

n <- 150 # número de mostres
p <- 2   # dimensions

sigma <- 1 # Variància de la distribució
mean1 <- 0 # centre del primer grup
mean2 <- 5 # centre del segon grup

n1 <- round(n/2) # número de mostres del primer grup
n2 <- round(n/2) # número de mostres del segon grup

x1 <- matrix(rnorm(n1*p,mean=mean1,sd=sigma),n1,p)
x2 <- matrix(rnorm(n2*p,mean=mean2,sd=sigma),n2,p)

Ajuntem totes les mostres generades i les mostrem en una gràfica

x  <- rbind(x1,x2)
plot (x, xlab="Grup 1", ylab="Grup 2")

Com es pot comprovar les mostres estan clarament separades en dos grups. Si es vol complicar el problema es pot modificar els punts centrals (mean1 i mean2) fent que estiguin més propers i/o ampliar la Variància (sigma) per a que les mostres estiguin més disperses.

A continuació aplicarem l’algoritme k-means amb 2, 4 i 8 clústers

fit2       <- kmeans(x, 2)
y_cluster2 <- fit2$cluster

fit4       <- kmeans(x, 4)
y_cluster4 <- fit4$cluster

fit8       <- kmeans(x, 8)
y_cluster8 <- fit8$cluster

Les variables y_cluster2, y_cluster4 i y_cluster8 contenen per a cada mostra l’identificador del clúster a les que han estat assignades. Per exemple, en el cas dels k=2 les mostres s’han assignat al clúster 1 o al 2.

y_cluster2
##   [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
##  [38] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
##  [75] 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [112] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [149] 1 1

Per a visualitzar els clústers podem fer servir la funció clusplot. Mirem l’agrupació amb 2 clústers i observem pràcticament no hi ha valors extrems i realment els dos clústers generats són homogenis.

clusplot(x, fit2$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)

amb 4 observem com el clúster de l’esquerra l’ha dividit en tres.

clusplot(x, fit4$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)

i amb 8. L’algoritme fa cas al que se li demana i ens genera 8 clústers tot i que visualment ja es veu que el resultat no és massa consistent.

clusplot(x, fit8$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)

També podem visualitzar el resultat del procés d’agrupament amb el següent codi per al cas de 2 clústers. L’ús de colors facilita la identificació visual de clústers.

plot(x[y_cluster2==1,],col='blue', xlim=c(min(x[,1]), max(x[,1])), ylim=c(min(x[,2]), max(x[,2])), xlab = "Dimensió 1", ylab = "Dimensió 2")
points(x[y_cluster2==2,],col='red')

per a 4

plot(x[y_cluster4==1,],col='blue', xlim=c(min(x[,1]), max(x[,1])), ylim=c(min(x[,2]), max(x[,2])), xlab = "Dimensió 1", ylab = "Dimensió 2")
points(x[y_cluster4==2,],col='red')
points(x[y_cluster4==3,],col='green')
points(x[y_cluster4==4,],col='black')

i per a 8

plot(x[y_cluster8==1,],col='blue', xlim=c(min(x[,1]), max(x[,1])), ylim=c(min(x[,2]), max(x[,2])), xlab = "Dimensió 1", ylab = "Dimensió 2")
points(x[y_cluster8==2,],col='red')
points(x[y_cluster8==3,],col='green')
points(x[y_cluster8==4,],col='black')
points(x[y_cluster8==5,],col='yellow')
points(x[y_cluster8==6,],col='purple')
points(x[y_cluster8==7,],col='cyan')
points(x[y_cluster8==8,],col='orange')

Ara avaluarem la qualitat de l’agregació. Per això farem servir la funció silhouette que calcula la silueta de cada mostra

d  <- daisy(x) 
sk2 <- silhouette(y_cluster2, d)
sk4 <- silhouette(y_cluster4, d)
sk8 <- silhouette(y_cluster8, d)

La funció silhouette retorna per a cada mostra, el clúster on ha estat assignat, el clúster veí i el valor de la silueta. Així doncs, calculant la mitjana de la tercera columna podem obtenir una estimació de la qualitat de l’agrupament.

mean(sk2[,3])
## [1] 0.7430604
mean(sk4[,3])
## [1] 0.4956154
mean(sk8[,3])
## [1] 0.3540149

Com es pot comprovar, agrupar en dos clústers es millor que en 4 o en 8, lo qual es lògic tenint en compte com s’han generat les dades.

Una bona pràctica alhora d’entendre millor el joc de dades, consisteix en posar nom a cadascun dels clústers identificats. Ho veurem més clarament en el següent exemple que parteix de dades reals.


2 Exemple guiat 1.2

2.1 Mètodes d’agregació k-means amb dades reals


A continuació estudiarem un altre exemple de com es fan servir els models d’agregació. Per a això farem servir el joc de dades penguins contingut en el paquet R palmerpenguins. Aquest joc de dades es troba descrit a https://cran.r-project.org/web/packages/palmerpenguins/index.html i conté medicions de grandària, observacions de postes i proporcions d’isòtops sanguinis de tres espècies de pingüins observades en tres illes de l’arxipèlag Palmer, a l’Antàrtida, durant un període d’estudi de tres anys.

Aquest dataset està prèviament treballat perquè les dades estiguin netes i sense errors. Si no és així abans de res hauríem de buscar errors, valors nuls o outliers. Hauríem tractar de discretitzar o eliminar columnes. Fins i tot realitzar aquest últim pas diverses vegades per comprovar els diferents resultats i triar el que millor rendiment ens doni. De totes maneres conté algun valor nul que procedirem a ignorar.

Procedim a visualitzar l’estructura i resum del joc de dades.

if (!require('palmerpenguins')) install.packages('palmerpenguins')
library(palmerpenguins)
# palmerpenguins::penguins
summary(penguins)
##       species          island    bill_length_mm  bill_depth_mm  
##  Adelie   :152   Biscoe   :168   Min.   :32.10   Min.   :13.10  
##  Chinstrap: 68   Dream    :124   1st Qu.:39.23   1st Qu.:15.60  
##  Gentoo   :124   Torgersen: 52   Median :44.45   Median :17.30  
##                                  Mean   :43.92   Mean   :17.15  
##                                  3rd Qu.:48.50   3rd Qu.:18.70  
##                                  Max.   :59.60   Max.   :21.50  
##                                  NA's   :2       NA's   :2      
##  flipper_length_mm  body_mass_g       sex           year     
##  Min.   :172.0     Min.   :2700   female:165   Min.   :2007  
##  1st Qu.:190.0     1st Qu.:3550   male  :168   1st Qu.:2007  
##  Median :197.0     Median :4050   NA's  : 11   Median :2008  
##  Mean   :200.9     Mean   :4202                Mean   :2008  
##  3rd Qu.:213.0     3rd Qu.:4750                3rd Qu.:2009  
##  Max.   :231.0     Max.   :6300                Max.   :2009  
##  NA's   :2         NA's   :2

Com es pot comprovar, aquesta base de dades està pensada per a problemes de classificació supervisada que pretén classificar cada tipus de pingüí en una de les tres classes o espècies existents (Adelie, Gentoo o Chinstrap). Com en aquest exemple farem servir un mètode no supervisat, transformarem el problema supervisat original en un no supervisat . Per aconseguir-ho no farem servir la columna species, que és la variable que es vol predir. Per tant, intentarem trobar agrupacions usant únicament els quatre atributs numèrics que caracteritzen cada espècie de pingüí.

Carreguem les dades i ens quedem únicament amb les quatre columnes que defineixen a cada espècie.

x <- na.omit(penguins[,3:6])

En aquest cas hem plantejat un exemple més realista i per tant inicialment no coneixem el número òptim de clústers. Comencem provant amb varis valors.

d <- daisy(x) 
resultados <- rep(0, 10)
for (i in c(2,3,4,5,6,7,8,9,10))
{
  fit           <- kmeans(x, i)
  y_cluster     <- fit$cluster
  sk            <- silhouette(y_cluster, d)
  resultados[i] <- mean(sk[,3])
}

Mostrem en una gràfica els valors de la silueta mitja de cada prova per comprovar quin número de clusters és el millor.

plot(2:10,resultados[2:10],type="o",col="blue",pch=0,xlab="Número de clusters",ylab="Silueta")

Tot i que un esperaria obtenir un valor òptim per a k = 3, sembla que del gràfic es desprèn que es millor k = 4 o fins i tot k = 5.

Un altre forma d’avaluar quin és el millor nombre de clústers és considerar el millor model, aquell que ofereix la menor suma dels quadrats de les distàncies dels punts de cada grup respecte al seu centre (withinss), amb la major separació entre centres de grups (betweenss). Com es pot comprovar és una idea conceptualment similar a la silueta. Una manera comuna de fer la selecció del nombre de clústers consisteix a aplicar el mètode elbow (colze), que no és més que la selecció del nombre de clústers d’acord amb la inspecció de la gràfica que s’obté al iterar amb el mateix conjunt de dades per a diferents valors de nombre de clústers. S’ha de seleccionar el valor que es troba en el “colze” de la corba.

resultados <- rep(0, 10)
for (i in c(2,3,4,5,6,7,8,9,10))
{
  fit           <- kmeans(x, i)
  resultados[i] <- fit$tot.withinss
}
plot(2:10,resultados[2:10],type="o",col="blue",pch=0,xlab="Nombre de clústers",ylab="tot.tot.withinss")

En aquest cas el número òptim de clústers es 4, que és quan la corba comença a estabilitzar-se.

També es pot fer servir la funció kmeansruns del paquet fpc que executarà l’algoritme kmeans com un conjunt de valors i seleccionarà el valor del número de clústers que millor funcioni d’acord amb dos criteris: la silueta mitja (asw) i Calinski-Harabasz (“ch”).

if (!require('fpc')) install.packages('fpc'); library('fpc')
fit_ch  <- kmeansruns(x, krange = 1:10, criterion = "ch") 
fit_asw <- kmeansruns(x, krange = 1:10, criterion = "asw") 

Podem comprovar el valor amb el que s’ha obtingut el millor resultat i també mostrar el resultat obtingut per a tots els valors de k fent servir tots dos criteris.

fit_ch$bestk
## [1] 10
fit_asw$bestk
## [1] 2
plot(1:10,fit_ch$crit,type="o",col="blue",pch=0,xlab="Número de clústers",ylab="Criteri Calinski-Harabasz")

plot(1:10,fit_asw$crit,type="o",col="blue",pch=0,xlab="Número de clústers",ylab="Criteri silueta mitja")

Els resultats son molt semblants als que hem obtingut anteriorment. Amb el criteri de la silueta mitja s’obtenen dos clústers i amb el Calinski-Harabasz s’obtenen 3.

Com s’ha comprovat, conèixer el número òptim de clústers no és un problema fàcil. Tampoc ho és la visualització dels models d’agregació.

Com en el cas que estudiem sabem que les dades poden ser agrupades en 3 classes, vegem com es comporta el kmeans en aquest cas. Per això comparem visualment els camps dos a dos, amb el valor real que sabem està emmagatzemat en el camp class del dataset original.

(Aclarim que òbviament no acostuma a passar que coneguem de forma prèvia el nombre de clústers òptim. Aquest exemple el plantegem amb finalitats didàctiques i amb voluntat d’experimentar)

penguins3clusters <- kmeans(x, 3)

# bill_lLength y bill_depth
plot(x[c(1,2)], col=penguins3clusters$cluster, main="Classificació k-means")

plot(x[c(1,2)], col=as.factor(penguins$species), main="Classificació real")

Podem observar que flipper_length i body_mass no són bons indicadors per diferenciar a les tres subespècies, atès que dues de les subespècies estan massa barrejades per poder diferenciar res.

# flipper_length y body_mass
plot(x[c(3,4)], col=penguins3clusters$cluster, main="Classificació k-means")

plot(x[c(3,4)], col=as.factor(penguins$species), main="Classificació real")

# bill_length y flipper_length
plot(x[c(1,3)], col=penguins3clusters$cluster, main="Classificació k-means")

plot(x[c(1,3)], col=as.factor(penguins$species), main="Classificació real")

Les dues mesures de bill semblen aconseguir millors resultats al dividir les tres espècies de pingüins. El grup format pels punts negres que ha trobat l’algoritme coincideix amb els de l’espècie Adelie. Els altres dos grups però es barregen més, i hi ha certs punts que es classifiquen com Gentoo (verd) quan en realitat són Chinstrap (vermell).

Una bona tècnica que ajuda a entendre els grups que s’han format, és mirar de donar-los un nom. Com per exemple:

  • Grup 1: Només Adelie (color negre)
  • Grup 2: Principalment Chinstrap (color vermell)
  • Grup 3: Barreja de Gentoo (color verd) i Adelie (color negre)

Això ens ajuda a entendre com estan formats els grups i a referir-nos a ells en anàlisis posteriors.

Tot plegat ens indica que establir el nombre de grups o clústers en un joc de dades no és un aspecte que puguem assegurar que sempre encertarem amb precisió i a més ho farem de forma objectiva, ven al contrari és un àmbit d’estudi que requereix d’anàlisi en si mateix.

Us deixem en el següent enllaç un material didàctic complementari que us pot ajudar a aprofundir en el tema de la selecció del nombre clúster més adequat per a un joc de dades:
datascience.recursos.uoc.edu

Com a continuació de l’estudi podríem seguir experimentant combinant en gràfics similars als anteriors. En definitiva es tractaria en aquest punt d’aprofundir més en el coneixement de les propietats de les diferents característiques o columnes de el joc de dades.


3 Exemple guiat 2

3.1 Mètodes basats en densitat: DBSCAN i OPTICS


En el següent exemple treballarem els algoritmes DBSCAN i OPTICS com a mètodes de clustering que permeten la generació de grups no radials a diferència de k-means. Veurem que el seu paràmetre de entrada més rellevant és minPts que defineix la mínima densitat acceptada al voltant d’un centroide.

Incrementar aquest paràmetre ens permetrà reduir el soroll (observacions no assignades a cap clúster), en qualsevol cas començarem per construir el nostre propi joc de dades en el que dibuixarem 4 zones de punts diferenciades.

if (!require('dbscan')) install.packages('dbscan'); library('dbscan')
set.seed(2)
n <- 400
x <- cbind(
x = runif(4, 0, 1) + rnorm(n, sd=0.1),
y = runif(4, 0, 1) + rnorm(n, sd=0.1)
)
plot(x, col=rep(1:4, time = 100))

Una de las primeres activitats que realitza l’algoritme és ordenar les observacions de forma que els punts més propers es converteixin en veïns en l’ordenament. Es podria pensar com una representació numèrica del dendograma d’una agrupació jeràrquica.

### Executem l'algoritme OPTICS deixant el paràmetre eps amb el seu valor per defecte i fixant el criteri de veïnatge en 10
res <- optics(x, minPts = 10)
res
## OPTICS ordering/clustering for 400 objects.
## Parameters: minPts = 10, eps = 0.193786846197958, eps_cl = NA, xi = NA
## Available fields: order, reachdist, coredist, predecessor, minPts, eps,
##                   eps_cl, xi
### Obtenim la ordenació de les observacions o punts
res$order
##   [1]   1 363 209 349 337 301 357 333 321 285 281 253 241 177 153  57 257  29
##  [19]  77 169 105 293 229 145 181 385 393 377 317 381 185 117 101   9  73 237
##  [37] 397 369 365 273 305 245 249 309 157 345 213 205  97  49  33  41 193 149
##  [55]  17  83 389  25 121 329   5 161 341 217 189 141  85  53 225 313 289 261
##  [73] 221 173  69  61 297 125  81 133 129 197 109 137  59  93 165  89  21  13
##  [91] 277 191 203 379 399 375 351 311 235 231 227  71  11 299 271 291 147  55
## [109]  23 323 219 275  47 263   3 367 331 175  87 339 319 251 247 171 111 223
## [127]  51  63 343 303 207 151 391 359 287 283 215 143 131 115  99  31 183  43
## [145] 243 199  79  27 295  67 347 255 239 195 187 139 107  39 119 179 395 371
## [163] 201 123 159  91 211 355 103 327  95   7 167  35 267 155 387 383 335 315
## [181] 259 135  15 113 279 373   4 353 265 127  45  37  19 276 224 361 260 288
## [199] 336 368 348 292 268 252 120 108  96  88  32  16 340 156 388 372 356 332
## [217] 304 220 188 168 136 124  56 236  28 244 392 184  76 380 232 100 116 112
## [235] 256  72   8 280  64  52 208 172 152 148 360 352 192 160 144 284 216  48
## [253]  84  92  36  20 212 272 264 200 128  80 180 364 196  12 132  40 324 308
## [271] 176 164  68 316 312 384 300 344 328 248 204 140 296  24 320 228  60  44
## [289] 233  65 400 376 240 163 104 396 307  75  14 325 269 262 234 382 294 206
## [307] 198 374 310 362 318 386 358 330 278 210 298 282 122  98  34  26 174 142
## [325]  46   6  62 118 190 202 114 322 286  38 242 394 342 266 162 130  30 182
## [343]   2  74 314 290 246 194 170 126 158 378 350 254 226 214  70  18  10 366
## [361] 354 186 150  86 306 102 338 346 134 250 138  94  78 390 274  58  42 258
## [379]  66  90 146 370 222 218 326  82 110 270 334 178 166 398  22  50 238 106
## [397] 154 302 230  54

Un altre pas molt interessant de l’algoritme és la generació d’un diagrama d’accessibilitat o reachability plot, en el que s’aprecia d’una forma visual la distància d’accessibilitat de cada punt.

Les valls representen clústers (com més profund és la vall, més dens és el clúster), mentre que els cims indiquen els punts que estan entre les agrupacions (aquests punts són candidats a ser considerats outliers)

### Gràfic d'accessibilitat
plot(res)

Vegem una altra representació del diagrama d’accessibilitat, on podem observar les traces de les distàncies entre punts propers del mateix clúster i entre clústers diferents.

### Dibuixem les traces que relacionen punts
plot(x, col = "grey")
polygon(x[res$order,])

Un altre exercici interessant a realitzar és extraure una agrupació de la ordenació realitzada per OPTICS similar a lo que DBSCAN hagués generat establint el paràmetre eps en eps_cl = 0.065. En aquest sentit convidem l’estudiant a experimentar amb diferents valors d’aquest paràmetre.

### Extracció d'un clústering DBSCAN tallant l'accessibilitat en el valor eps_cl
res <- extractDBSCAN(res, eps_cl = .065)
res
## OPTICS ordering/clustering for 400 objects.
## Parameters: minPts = 10, eps = 0.193786846197958, eps_cl = 0.065, xi = NA
## The clustering contains 4 cluster(s) and 92 noise points.
## 
##  0  1  2  3  4 
## 92 81 84 72 71 
## 
## Available fields: order, reachdist, coredist, predecessor, minPts, eps,
##                   eps_cl, xi, cluster
plot(res) ## negre indica soroll

Observem en el gràfic anterior com s’han pintat de color els 4 clústers i en negre es mantenen els valors outliers o extrems.

Seguim endavant amb una representació gràfica que ens mostra els clústers mitjançant formes convexes.

hullplot(x, res)

Repetim l’experiment anterior incrementant el paràmetre epc_c, vegem com l’efecte que produeix és la concentració de clústers ja que flexibilitzem la condició de densitat

### Incrementem el paràmetre eps
res <- extractDBSCAN(res, eps_cl = .1)
res
## OPTICS ordering/clustering for 400 objects.
## Parameters: minPts = 10, eps = 0.193786846197958, eps_cl = 0.1, xi = NA
## The clustering contains 2 cluster(s) and 9 noise points.
## 
##   0   1   2 
##   9 295  96 
## 
## Available fields: order, reachdist, coredist, predecessor, minPts, eps,
##                   eps_cl, xi, cluster
plot(res)

hullplot(x, res)

Vegem ara una variant de la extracció DBSCN anterior. En ella el paràmetre xi ens servirà per a classificar els clústers en funció del canvi en la densitat relativa dels mateixos.

### Extracció del clustering jeràrquic en funció de la variació de la densitat pel mètode xi
res <- extractXi(res, xi = 0.05)
res
## OPTICS ordering/clustering for 400 objects.
## Parameters: minPts = 10, eps = 0.193786846197958, eps_cl = NA, xi = 0.05
## The clustering contains 7 cluster(s) and 1 noise points.
## 
## Available fields: order, reachdist, coredist, predecessor, minPts, eps,
##                   eps_cl, xi, cluster, clusters_xi
plot(res)

hullplot(x, res)

4 Exercicis

Els exercicis es realitzaran sobre la base del joc de dades Hawks present en el paquet R Stat2Data.

Els estudiants i el professorat del Cornell College a Mount Vernon, Iowa, van recollir dades durant molts anys al mirador de falcons de l’estany MacBride, prop d’Iowa City, a l’estat d’Iowa. El joc de dades que analitzem aquí és un subconjunt del conjunt de dades original, utilitzant només aquelles espècies per a les que hi havia més de 10 observacions. Les dades es van recollir en mostres aleatòries de tres espècies diferents de falcons: Cua-roja, Esparver i Falcó de Cooper.

Hem seleccionat aquest joc de dades per la seva semblança amb el joc de dades penguins i pel seu potencial alhora d’aplicar-li algoritmes de mineria de dades no supervisats. Les variables numèriques en què us basareu són: Wing, Weight, culmen, Hallux

if (!require('Stat2Data')) install.packages('Stat2Data'); library('Stat2Data')
data("Hawks")
summary(Hawks)
##      Month             Day             Year       CaptureTime   ReleaseTime 
##  Min.   : 8.000   Min.   : 1.00   Min.   :1992   11:35  : 14          :842  
##  1st Qu.: 9.000   1st Qu.: 9.00   1st Qu.:1995   13:30  : 14   11:00  :  2  
##  Median :10.000   Median :16.00   Median :1999   11:45  : 13   11:35  :  2  
##  Mean   : 9.843   Mean   :15.74   Mean   :1998   12:10  : 13   12:05  :  2  
##  3rd Qu.:10.000   3rd Qu.:23.00   3rd Qu.:2001   14:00  : 13   12:50  :  2  
##  Max.   :11.000   Max.   :31.00   Max.   :2003   13:05  : 12   13:32  :  2  
##                                                  (Other):829   (Other): 56  
##       BandNumber  Species  Age     Sex          Wing           Weight      
##            :  2   CH: 70   A:224    :576   Min.   : 37.2   Min.   :  56.0  
##  1142-09240:  1   RT:577   I:684   F:174   1st Qu.:202.0   1st Qu.: 185.0  
##  1142-09241:  1   SS:261           M:158   Median :370.0   Median : 970.0  
##  1142-09242:  1                            Mean   :315.6   Mean   : 772.1  
##  1142-18229:  1                            3rd Qu.:390.0   3rd Qu.:1120.0  
##  1142-19209:  1                            Max.   :480.0   Max.   :2030.0  
##  (Other)   :901                            NA's   :1       NA's   :10      
##      Culmen         Hallux            Tail        StandardTail  
##  Min.   : 8.6   Min.   :  9.50   Min.   :119.0   Min.   :115.0  
##  1st Qu.:12.8   1st Qu.: 15.10   1st Qu.:160.0   1st Qu.:162.0  
##  Median :25.5   Median : 29.40   Median :214.0   Median :215.0  
##  Mean   :21.8   Mean   : 26.41   Mean   :198.8   Mean   :199.2  
##  3rd Qu.:27.3   3rd Qu.: 31.40   3rd Qu.:225.0   3rd Qu.:226.0  
##  Max.   :39.2   Max.   :341.40   Max.   :288.0   Max.   :335.0  
##  NA's   :7      NA's   :6                        NA's   :337    
##      Tarsus        WingPitFat        KeelFat           Crop       
##  Min.   :24.70   Min.   :0.0000   Min.   :0.000   Min.   :0.0000  
##  1st Qu.:55.60   1st Qu.:0.0000   1st Qu.:2.000   1st Qu.:0.0000  
##  Median :79.30   Median :1.0000   Median :2.000   Median :0.0000  
##  Mean   :71.95   Mean   :0.7922   Mean   :2.184   Mean   :0.2345  
##  3rd Qu.:87.00   3rd Qu.:1.0000   3rd Qu.:3.000   3rd Qu.:0.2500  
##  Max.   :94.00   Max.   :3.0000   Max.   :4.000   Max.   :5.0000  
##  NA's   :833     NA's   :831      NA's   :341     NA's   :343

4.1 Exercici 1

Presenta el joc de dades, nom i significat de cada columna, així com les distribucions dels seus valors.

Realitza un estudi aplicant el mètode K-means, similar al dels exemples 1.1 i 1.2

4.1.1 Resposta 1

Escriu aquí la resposta a la pregunta

4.2 Exercici 2

Amb el joc de dades proporcionat realitza un estudi aplicant DBSCAN i OPTICS, similar al de l’exemple 2

4.2.1 Resposta 2

Escriu aquí la resposta a la pregunta

4.3 Exercici 3

Realitza una comparativa dels mètodes k-means i DBSCAN

4.3.1 Resposta 3

Escriu aquí la resposta a la pregunta